package com.flca.frw.components
{
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	
	import flash.ui.Keyboard;
	
	import mx.controls.TextInput;
	
	public class TimeInput extends TextInput {
		private var hourValue:int;
		private var minuteValue:int;
		private var amPmValue:Boolean;
		
		private var textChanged:Boolean = false;
		private var lockedOn:String = null;
		private var lastValidated:String = null;
		
		public function TimeInput() {
			super();
			hourValue = 1;
			minuteValue = 0;
			amPmValue = false;
			width = 65;
			
			validateTime();
			
			// Add listeners
			addEventListener(Event.CHANGE, changed);
			addEventListener(FocusEvent.FOCUS_IN, focusIn);
			addEventListener(FocusEvent.FOCUS_OUT, validateText);
			addEventListener(KeyboardEvent.KEY_DOWN, validateKey);
			addEventListener(KeyboardEvent.KEY_UP, validateUp);
		}
		
		private function validateUp(event:KeyboardEvent):void {
			if ((event.keyCode == Keyboard.UP) || (event.keyCode == Keyboard.DOWN)) {
				lockedOn = null;
			} else if (event.keyCode == Keyboard.ENTER) {
				validateText();
			}
		}
		
		private function validateKey(event:KeyboardEvent):void {
			var change:int = 0;
			if (event.keyCode == Keyboard.UP) {
				validateText();
				change = 1;
			} else if (event.keyCode == Keyboard.DOWN) {
				validateText();
				change = -1;
			}
			if (change != 0) {
				if (lockedOn == null) {
					if (text.indexOf(':') >= selectionBeginIndex) {
						lockedOn = 'hour';
					} else if (text.indexOf(' ') >= selectionBeginIndex) {
						lockedOn = 'minute';
					} else {
						lockedOn = 'amPm';
					}
				}
				
				if (lockedOn == 'hour') {
					hourValue += change;
					if (change == 1) {
						if (hourValue == 12) {
							amPmValue = !amPmValue;
						} else if (hourValue == 13) {
							hourValue = 1;
						}
					}
				} else if (lockedOn == 'minute') {
					minuteValue += change;
				} else {
					amPmValue = !amPmValue;
				}
				validateTime();
				if (lockedOn == 'hour') {
					selectionBeginIndex = 0;
					selectionEndIndex = 2;
				} else if (lockedOn == 'minute') {
					selectionBeginIndex = 3;
					selectionEndIndex = 5;
				} else {
					selectionBeginIndex = 6;
					selectionEndIndex = 8;
				}
			}
		}
		
		private function changed(event:Event = null):void {
			textChanged = true;
		}
		
		private function focusIn(event:Event = null):void {
			selectionBeginIndex = 0;
			selectionEndIndex = length;
		}
		
		private function validateText(event:Event = null):void {
			if (textChanged) {
				textChanged = false;
				
				// Process the text
				
				// Validate AM / PM
				var apSet:Boolean = false;
				if (text.toLowerCase().indexOf('p') != -1) {
					amPmValue = true;
					apSet = true;
				} else if (text.toLowerCase().indexOf('a') != -1) {
					amPmValue = false;
					apSet = true;
				}
				
				var n:String = '';
				if (text.indexOf(':') != -1) {
					// Split and process
					n = text.substring(0, text.indexOf(':'));
					hourValue = parseInt(n);
					n = text.substring(text.indexOf(':') + 1);
					minuteValue = parseInt(n);
				} else {
					// Get only numeric values
					n = getNumbers(text);
					if (n.length == 1) {
						hourValue = parseInt(n);
						minuteValue = 0;
					} else if (n.length == 2) {
						if (parseInt(n) <= 12) {
							hourValue = parseInt(n);
							minuteValue = 0;
						} else {
							hourValue = parseInt(n.charAt(0));
							minuteValue = parseInt(n.charAt(1));
						}
					} else if (n.length == 3) {
						hourValue = parseInt(n.charAt(0));
						minuteValue = parseInt(n.charAt(1) + n.charAt(2));
					} else if (n.length >= 4) {
						hourValue = parseInt(n.charAt(0) + n.charAt(1));
						if (!apSet) {
							if (hourValue > 12) {
								amPmValue = true;
								hourValue -= 12;
							} else {
								amPmValue = false;
							}
						}
						minuteValue = parseInt(n.charAt(2) + n.charAt(3));
					}
				}
				
				validateTime();
			}
		}
		
		private function getNumbers(s:String):String {
			var n:String = '';
			var c:String;
			for (var i:int = 0; i < s.length; i++) {
				c = s.charAt(i);
				if (!isNaN(parseInt(c))) {
					n += c;
				}
			}
			return n;
		}
		
		private function validateTime():void {
			if (minuteValue > 60) {
				hourValue++;
				minuteValue -= 60;
				if (minuteValue > 59) minuteValue = 59;
			} else if (minuteValue < 0) {
				hourValue--;
				minuteValue += 60;
				if (minuteValue < 0) minuteValue = 0;
			}
			if (hourValue > 12) {
				amPmValue = !amPmValue;
				hourValue -= 12;
				if (hourValue > 12) hourValue = 12;
			} else if (hourValue < 1) {
				amPmValue = !amPmValue;
				hourValue += 12;
				if (hourValue < 0) hourValue = 0;
			}
			
			text = format(hourValue) + ':' + format(minuteValue) + ' ' + formatBoolean(amPmValue);
			if (lastValidated != null) {
				if (lastValidated != text) {
					dispatchEvent(new Event('timeChange'));
				}
			}
			lastValidated = text;
		}
		
		private function format(n:int):String {
			if (n < 10) return '0' + n;
			return n.toString();
		}
		
		private function formatBoolean(n:Boolean):String {
			if (n) return 'pm';
			return 'am';
		}
		
		public function set hour(_hour:int):void {
			hourValue = _hour;
			validateTime();
		}
		
		public function get hour():int {
			return hourValue;
		}
		
		public function set minute(_minute:int):void {
			minuteValue = _minute;
			validateTime();
		}
		
		public function get minute():int {
			return minuteValue
		}
		
		public function set am_pm(_amPm:String):void {
			amPmValue = _amPm == 'pm';
			validateTime();
		}
		
		public function get am_pm():String {
			return amPmValue ? 'pm' : 'am';
		}
	}
}
